package com.mjk.common.tools.springextend;

import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.stereotype.Repository;
import org.springframework.util.Assert;

import java.lang.annotation.Annotation;
import java.util.Map;
import java.util.Map.Entry;
@Repository
public class BeeSpringBean implements ApplicationContextAware {

	private static ConfigurableApplicationContext context = null;
	private static BeeSpringBean stools = null;

	public static synchronized  BeeSpringBean init() {
		if (stools == null) {
			stools = new BeeSpringBean();
		}
		return stools;
	}

	public void setApplicationContext(ApplicationContext applicationContext)
			throws BeansException {
		context = (ConfigurableApplicationContext) applicationContext;
	}

	public static synchronized  Object getBean(String beanName) {
		return context.getBean(beanName);
	}
	
	public static synchronized  <T> T getBean(Class<T> clazz) {
		try{
			return context.getBean(clazz);
		}catch(Exception e){
			return null;
		}
	}
	 /**
     * 判断一个bean是否存在Spring容器中.
     *
     * @param type 类型
     * @return 成功 true 失败 false
     */
	public static synchronized  boolean exitBean(Class type){
		return context.containsBean(type.getName());
	}
	
	 /**
     * 动态注册一个Bean动Spring容器中
     *
     * @param beanName  名称
     * @param beanClazz 定义bean
     */
    public static void registerBean(String beanName, Class beanClazz, Map<String, Object> propertys) {
    	Assert.notNull(beanName,"beanName not null");
        Assert.notNull(beanClazz,"beanClazz not null");
        BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(beanClazz);
        if (propertys != null) {
        	for(Entry<String, Object> entry : propertys.entrySet()){
        		builder.addPropertyValue(entry.getKey(), entry.getValue());
        	}
        }
        builder.setScope(BeanDefinition.SCOPE_SINGLETON);
        registerBean(beanName, builder.getBeanDefinition());

    }

    public static void registerBean(String beanName, Object obj) {
    	Assert.notNull(beanName,"beanName not null");
    	Assert.notNull(obj,"obj not null");
        context.getBeanFactory().registerSingleton(beanName, obj);
    }

    /**
     * 注册Bean信息
     *
     * @param beanDefinition
     */
    public static void registerBean(String beanName, BeanDefinition beanDefinition) {
        BeanDefinitionRegistry beanDefinitionRegistry = (BeanDefinitionRegistry) context.getBeanFactory();
        beanDefinitionRegistry.registerBeanDefinition(beanName, beanDefinition);
    }

	/**
	 * 根据类型获取beans
	 * @param annotationType
	 * @return
	 */
	public static <T> Map<String, T> getBeansOfType(Class<T> annotationType) {
		Assert.notNull(annotationType,"annitationType not null");
		return context.getBeansOfType(annotationType);
	}

    /**
     * 根据枚举类型获取Spring注册的Bean
     *
     * @param annotationType 枚举
     * @return
     */
    public Map<String, Object> getBeanWithAnnotation(Class<? extends Annotation> annotationType) {
    	Assert.notNull(annotationType,"annitationType not null");
        return context.getBeansWithAnnotation(annotationType);
    }

    /**
     * 动态注册一个Bean动Spring容器中
     *
     * @param beanName  名称
     * @param beanClazz 定义bean
     */
    public static void registerBean(String beanName, Class beanClazz) {
        registerBean(beanName, beanClazz, null);
    }
	/**
	 * 获取spring.profiles.active
	 * @return
	 */
    public static String getActiveProfile() {
    	return context.getEnvironment().getActiveProfiles()[0];
    }

	/**
	 * 获取配置环境中某个key的值
	 * @param key
	 * @return
	 */
	public static String getEnvValue(String key){
		return context.getEnvironment().getProperty(key);
	}
}
